#include "QueueManager.h"


QueueManager::QueueManager(void)
{
}


QueueManager::~QueueManager(void)
{
}

bool QueueManager::ifNeedsProcessing( const Cell* currCell)
{
	//cout<<"THREAD2: WE ARE IN ifNeedsProcessing\n";
	
	bool result = false;
	int num_bl = 0;
	int num_fr = 0;
	int currCellCond;
	{
		boost::lock_guard<boost::mutex> lock(CPMutex);
		num_bl = currCell->getDirection().num_blocked;
		num_fr = currCell->getDirection().num_free;
		currCellCond = currCell->getCondition();
	}
	if ( \
		( \
		( \
		(num_bl == UP \
		|| num_bl == DOWN \
		|| num_bl == LEFT \
		|| num_bl == RIGHT) \
		|| \
		(num_fr == UP \
		|| num_fr == DOWN \
		|| num_fr == LEFT \
		|| num_fr == RIGHT)\
		) \
		&& (NOT == currCellCond) \
		) \
		|| \
		( \
		(
		(num_bl != UP \
		|| num_bl != DOWN \
		|| num_bl != LEFT \
		|| num_bl != RIGHT \
		|| num_bl != 0) \
		|| \
		(num_fr != UP \
		|| num_fr != DOWN \
		|| num_fr != LEFT \
		|| num_fr != RIGHT \
		|| num_bl != 0) \
		) \
		&& (currCellCond != READY) \
		) \
	   )
	{
		result = true;
	}
				   
	//cout<<"THREAD2: WE ARE LEAVING ifNeedsProcessing\n";
	return result;
}

void QueueManager::ProcessingLogic()
{
	cout<<"THREAD2: Queue manager processing logic works\n";
	CellProcessor whiteProcessor(&cond_var.AddedtoQmQ, &cond_var.condWhAdded, &cond_var.condWhFinished, &proc_ques.white);
	//CellProcessor blackProcessor(&cond_var.AddedtoQmQ, &cond_var.condBlAdded, &cond_var.condBlFinished, &proc_ques.black);
	//CellProcessor greyProcessor(&cond_var.AddedtoQmQ, &cond_var.condGrAdded, &cond_var.condGrFinished, &proc_ques.grey);
	while (true)
	{
		while(!qmQ().empty())		//not sure if it's atomic and should be improved!!
		{
			Cell* curCell = 0;
			cout<<"THREAD2: QmQ white size: "<<proc_ques.white.size()<<endl;
			{
				boost::lock_guard<boost::mutex> lock(QmQMutex);
				curCell = qmQ().back();
				qmQ().pop();
			}
			if (ifNeedsProcessing(curCell))
			{
				boost::lock_guard<boost::mutex> lock(CPMutex);
				switch (curCell->getColor())
				{
				case WHITE:
					proc_ques.white.push(curCell);
					cond_var.condWhAdded.notify_one();
					break;
				case BLACK:
					proc_ques.black.push(curCell);
					cond_var.condBlAdded.notify_one();
					break;
				case GREY:
					proc_ques.grey.push(curCell);
					cond_var.condGrAdded.notify_one();
					break;
				default:
					cout<<"ERROR!!!!: wrong color received!";
				}
			}
			cout<<"THREAD2: Lets notify in QM that we pushed\n";
		}
		boost::unique_lock<boost::mutex> lock(QmQMutex);
		cond_var.AddedtoQmQ.wait(lock);
	}
	whiteProcessor.join();
	//blackProcessor.join();
	//greyProcessor.join();

	

}
